/*
Copyright SecureKey Technologies Inc. All Rights Reserved.

SPDX-License-Identifier: Apache-2.0
*/

package dispatcher

import (
	cb "git.cloud.inspur.com/ichain/ichain-protos-go/common"
	pb "git.cloud.inspur.com/ichain/ichain-protos-go/inode"
	"git.cloud.inspur.com/ichain/ichain-sdk-go/pkg/providers/ichain"
)

// Event 事件接口
type Event interface{}

// RegisterEvent 注册事件
type RegisterEvent struct {
	RegCh chan<- ichain.Registration // 注册通道
	ErrCh chan<- error               // 错误通道
}

// StopEvent 停止事件
type StopEvent struct {
	ErrCh chan<- error
}

// RegisterBlockEvent 注册区块事件
type RegisterBlockEvent struct {
	RegisterEvent
	Reg *BlockReg
}

// RegisterFilteredBlockEvent 注册过滤的区块事件
type RegisterFilteredBlockEvent struct {
	RegisterEvent
	Reg *FilteredBlockReg
}

// RegisterContractEvent 注册合约事件
type RegisterContractEvent struct {
	RegisterEvent
	Reg *ContractReg
}

// RegisterTxStatusEvent 注册交易状态的事件
type RegisterTxStatusEvent struct {
	RegisterEvent
	Reg *TxStatusReg
}

// UnregisterEvent 取消注册事件
type UnregisterEvent struct {
	Reg ichain.Registration
}

// RegistrationInfo 注册信息对象
type RegistrationInfo struct {
	TotalRegistrations            int // 总注册数量
	NumBlockRegistrations         int // 注册区块事件的数量
	NumFilteredBlockRegistrations int // 注册过滤区块事件的数量
	NumCCRegistrations            int // 注册合约事件的数量
	NumTxStatusRegistrations      int // 注册交易状态事件的数量
}

type RegistrationInfoEvent struct {
	RegInfoCh chan<- *RegistrationInfo
}

func NewRegisterBlockEvent(filter ichain.BlockFilter, eventch chan<- *ichain.BlockEvent, respch chan<- ichain.Registration, errCh chan<- error) *RegisterBlockEvent {
	return &RegisterBlockEvent{
		Reg:           &BlockReg{Filter: filter, Eventch: eventch},
		RegisterEvent: NewRegisterEvent(respch, errCh),
	}
}

func NewRegisterFilteredBlockEvent(eventch chan<- *ichain.FilteredBlockEvent, respch chan<- ichain.Registration, errCh chan<- error) *RegisterFilteredBlockEvent {
	return &RegisterFilteredBlockEvent{
		Reg:           &FilteredBlockReg{Eventch: eventch},
		RegisterEvent: NewRegisterEvent(respch, errCh),
	}
}

func NewUnregisterEvent(reg ichain.Registration) *UnregisterEvent {
	return &UnregisterEvent{
		Reg: reg,
	}
}

func NewRegisterContractEvent(ccID, eventFilter string, eventch chan<- *ichain.ContractEvent, respch chan<- ichain.Registration, errCh chan<- error) *RegisterContractEvent {
	return &RegisterContractEvent{
		Reg: &ContractReg{
			ContractID:  ccID,
			EventFilter: eventFilter,
			Eventch:     eventch,
		},
		RegisterEvent: NewRegisterEvent(respch, errCh),
	}
}

func NewRegisterTxStatusEvent(txID string, eventch chan<- *ichain.TxStatusEvent, respch chan<- ichain.Registration, errCh chan<- error) *RegisterTxStatusEvent {
	return &RegisterTxStatusEvent{
		Reg:           &TxStatusReg{TxID: txID, Eventch: eventch},
		RegisterEvent: NewRegisterEvent(respch, errCh),
	}
}

func NewRegisterEvent(respch chan<- ichain.Registration, errCh chan<- error) RegisterEvent {
	return RegisterEvent{
		RegCh: respch,
		ErrCh: errCh,
	}
}

func NewBlockEvent(block *cb.Block, sourceURL string) *ichain.BlockEvent {
	return &ichain.BlockEvent{
		Block:     block,
		SourceURL: sourceURL,
	}
}

func NewFilteredBlockEvent(fblock *pb.FilteredBlock, sourceURL string) *ichain.FilteredBlockEvent {
	return &ichain.FilteredBlockEvent{
		FilteredBlock: fblock,
		SourceURL:     sourceURL,
	}
}

func NewContractEvent(contractID, eventName, txID string, payload []byte, blockNum uint64, sourceURL string) *ichain.ContractEvent {
	return &ichain.ContractEvent{
		ContractID:  contractID,
		EventName:   eventName,
		TxID:        txID,
		Payload:     payload,
		BlockNumber: blockNum,
		SourceURL:   sourceURL,
	}
}

func NewTxStatusEvent(txID string, txValidationCode pb.TxValidationCode, blockNum uint64, sourceURL string) *ichain.TxStatusEvent {
	return &ichain.TxStatusEvent{
		TxID:             txID,
		TxValidationCode: txValidationCode,
		BlockNumber:      blockNum,
		SourceURL:        sourceURL,
	}
}

func NewStopEvent(errch chan<- error) *StopEvent {
	return &StopEvent{
		ErrCh: errch,
	}
}

func NewRegistrationInfoEvent(regInfoCh chan<- *RegistrationInfo) *RegistrationInfoEvent {
	return &RegistrationInfoEvent{RegInfoCh: regInfoCh}
}
